home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / debugtx.arc / 06INSTR.DOC < prev    next >
Encoding:
Text File  |  1991-08-11  |  15.9 KB  |  317 lines

  1. CHAPTER 6    THE 86 INSTRUCTION SET                       6-1
  2.  
  3. Effective Addresses
  4.  
  5. Most memory data accessing in the 86 family is accomplished via 
  6. the mechanism of the effective address.  Wherever an effective 
  7. address specifier "eb", "ew" or "ed" appears in the list of 8086 
  8. instructions, you may use a wide variety of actual operands in 
  9. that instruction.  These include general registers, memory 
  10. variables, and a variety of indexed memory quantities.  
  11.  
  12. GENERAL REGISTERS: Wherever an "ew" appears, you can use any of 
  13.    the 16-bit registers AX,BX,CX,DX,SI,DI,SP, or BP.  Wherever an 
  14.    "eb" appears, you can use any of the 8-bit registers 
  15.    AL,BL,CL,DL,AH,BH,CH, or DH.  For example, the "ADD ew,rw" 
  16.    form subsumes the 16-bit register-to-register adds; for 
  17.    example, ADD AX,BX; ADD SI,BP; ADD SP,AX.  
  18.  
  19. MEMORY VARIABLES: Wherever an "ew" appears, you can use a word-
  20.    memory-variable.  Wherever an "eb" appears, you can use a 
  21.    byte-memory-variable.  Variables are typically declared in the 
  22.    DATA segment, using a DW declaration for a word-variable, or a 
  23.    DB declaration for a byte-variable.  For example, you can 
  24.    declare variables: 
  25.  
  26.      DATA_PTR  DW ?
  27.      ESC_CHAR  DB ?
  28.  
  29.    Later, you can load or store these variables:
  30.  
  31.      MOV SI,DATA_PTR    ; load DATA_PTR into SI for use
  32.      LODSW              ; fetch the word pointed to by DATA_PTR
  33.      MOV DATA_PTR,SI    ; store the value incremented by the LODSW
  34.      MOV BL,ESC_CHAR    ; load the byte-variable ESC_CHAR
  35.  
  36.    Alternatively, you can address specific unnamed memory 
  37.    locations by enclosing the location value in square brackets; 
  38.    for example, 
  39.  
  40.      MOV AL,[02000]     ; load contents of location 02000 into AL
  41.  
  42.    Note that A86 discerned from context (loading into AL) that a 
  43.    BYTE at 02000 was intended.  Sometimes this is impossible, and 
  44.    you must specify byte or word: 
  45.  
  46.      INC B[02000]       ; increment the byte at location 02000
  47.      MOV W[02000],0     ; set the WORD at location 02000 to zero
  48.                                                           6-2
  49. INDEXED MEMORY: The 86 supports the use of certain registers as 
  50.    base pointers and index registers into memory.  BX and BP are 
  51.    the base registers; SI and DI are the index registers.  You 
  52.    may combine at most one base register, at most one index 
  53.    register, and a constant number into a run-time pointer that 
  54.    determines the location of the effective address memory to be 
  55.    used in the instruction.  These can be given explicitly, by 
  56.    enclosing the index registers in brackets: 
  57.  
  58.         MOV AX,[BX]
  59.         MOV CX,W[SI+17]
  60.         MOV AX,[BX+BP+5]
  61.         MOV AX,[BX][BP]5 ; another way to write the same instr.
  62.  
  63.    Or, indexing can be accomplished by declaring variables in a 
  64.    based structure: 
  65.  
  66.         STRUC [BP]         ; NOTE based structures are unique to A86!
  67.           BP_SAVE   DW ?
  68.           RET_ADDR  DW ?
  69.           PARM1     DW ?
  70.           PARM2     DW ?
  71.         ENDS
  72.         INC PARM1         ; equivalent to INC W[BP+4]
  73.  
  74.     Finally, indexing can be done by mixing explicit components 
  75.     with declared ones: 
  76.  
  77.         TABLE    DB  4,2,1,3,5
  78.         MOV AL,TABLE[BX]
  79.  
  80.  
  81. Segmentation and Effective Addresses
  82.  
  83. The 86 family has four segment registers, CS, DS, ES, and SS, 
  84. used to address memory.  Each segment register points to 64K 
  85. bytes of memory within the 1-megabyte memory space of the 86.  
  86. (The start of the 64K is calculated by multiplying the segment 
  87. register value by 16; i.e., by shifting the value left by one hex 
  88. digit.)  If your program's code, data and stack areas can all fit 
  89. in the same 64K bytes, you can leave all the segment registers 
  90. set to the same value.  In that case, you won't have to think 
  91. about segment registers--no matter which one is used to address 
  92. memory, you'll still get the same 64K.  If your program needs 
  93. more than 64K, you must point one or more segment registers to 
  94. other parts of the memory space.  In this case, you must take 
  95. care that your memory references use the segment registers you 
  96. intended.  
  97.  
  98. Each effective address memory access has a default segment 
  99. register, to be used if you do not explicitly specify which 
  100. segment register you wish.  For most effective addresses, the 
  101. default segment register is DS.  The exceptions are those 
  102. effective addresses that use the BP register for indexing.  All 
  103. BP-indexed memory references have a default of SS.  (This is 
  104. because BP is intended to be used for addressing local variables, 
  105. stored on the stack.) 
  106.                                                           6-3
  107. If you wish your memory access to use a different segment 
  108. register, you provide a segment-override byte before the 
  109. instruction containing the effective address operand.  In the A86 
  110. language, you code the override by giving the name of the segment 
  111. register you wish before the instruction mnemonic.  For example, 
  112. suppose you want to load the AL register with the memory byte 
  113. pointed to by BX.  If you code MOV AL,[BX], the DS register will 
  114. be used to determine which 64K segment BX is pointing to.  If you 
  115. want the byte to come from the CS-segment instead, you code CS 
  116. MOV AL,[BX].  Be aware that the segment-override byte has effect 
  117. only upon the single instruction that follows it.  If you have a 
  118. sequence of instructions requiring overrides, you must give an 
  119. override byte before every instruction in the sequence.  (In that 
  120. case, you may wish to consider changing the value of the default 
  121. segment register for the duration of the sequence.) 
  122.  
  123. NOTE: This method for providing segment-overrides is unique to 
  124. the A86 assembler!  The assemblers provided by Intel and IBM (MS-
  125. DOS) attempt to figure out segment allocation for you, and plug 
  126. in segment-override bytes "behind your back".  In order to do 
  127. this, those assemblers require you to inform them which variables 
  128. and structures are pointed to by which segment registers.  That 
  129. is what the ASSUME directive in those assemblers is all about.  I 
  130. wrote Intel's first 86 assembler, ASM86, so I have been watching 
  131. the situation since day one.  Over the years, I have concluded 
  132. that the ASSUME-mechanism creates far, far more confusion that it 
  133. solves.  So I scrapped it; and the result is an assembler with 
  134. far less red tape.  But if your program needs more than 64K, you 
  135. do have to manage those segment registers yourself; so take care!  
  136.  
  137.  
  138. Effective Use of Effective Addresses
  139.  
  140. Remember that all of the common instructions of the 86 family 
  141. allow effective addresses as operands.  (The only major functions 
  142. that don't are the AL/AX specific ones: multiply, divide, and 
  143. input/output).  This means that you don't have to funnel many 
  144. through AL or AX just to do something with them.  You can perform 
  145. all the common arithmetic, PUSH/POP, and MOVes from any general 
  146. register to any general register; from any memory location 
  147. (indexed if you like) to any register; and (this is most often 
  148. overlooked) from any register TO memory.  The only thing you 
  149. can't do in general is memory-to-memory.  Among the more common 
  150. operations that inexperienced 86 programmers overlook are: 
  151.  
  152.    * setting memory variables to immediate values
  153.    * testing memory variables, and comparing them to constants
  154.    * preserving memory variables by PUSHing and POPping them
  155.    * incrementing and decrementing memory variables
  156.    * adding into memory variables
  157.                                                           6-4
  158. Encoding of Effective Addresses
  159.  
  160. Unless you are concerned with the nitty-gritty details of 86 
  161. instruction encoding, you don't need to read this section.  
  162.  
  163. Every instruction with an effective address has an encoded byte, 
  164. known as the effective address byte, following the 1-byte opcode 
  165. for the instruction. (For obscure reasons, Intel calls this byte 
  166. the ModRM byte.)  If the effective address is a memory variable, 
  167. or an indexed memory location with a non-zero constant offset, 
  168. then the effective address byte will be immediately followed by 
  169. the offset amount.  Amounts in the range -128 to +127 are given 
  170. by a single signed byte, denoted by "d8" in the table below.  
  171. Amounts requiring a 2-byte representation are denoted by "d16" in 
  172. the table below.  As with all 16-bit memory quantities in the 86 
  173. family, the word is stored with the least significant byte FIRST.  
  174.  
  175. The following table of effective address byte values is organized 
  176. into 32 rows and 8 columns.  The 32 rows give the possible values 
  177. for the effective address operand: 8 registers and 24 memory 
  178. indexing modes.  A 25th indexing mode, [BP] with zero 
  179. displacement, has been pre-empted by the simple-memory-variable 
  180. case.  If you code [BP] with no displacement, you will get 
  181. [BP]+d8, with a d8-value of zero.  
  182.  
  183. The 8 columns of the table reflect further information given by 
  184. the effective address byte.  Usually, this is the identity of the 
  185. other (always a register) operand of a 2-operand instruction.  
  186. Those instructions are identified by a "/r" following the opcode 
  187. byte in the instruction list.  Sometimes, the information given 
  188. supplements the opcode byte in identifying the instruction 
  189. itself.  Those instructions are identified by a "/" followed by a 
  190. digit from 0 through 7.  The digit tells which of the 8 columns 
  191. you should use to find the effective address byte.  
  192.  
  193. For example, suppose you have a perverse wish to know the precise 
  194. bytes encoded by the instruction SUB B[BX+17],100.  This 
  195. instruction subtracts an immediate quantity, 100, from an 
  196. effective address quantity, B[BX+17].  By consulting the 
  197. instruction list, you find the general form SUB eb,ib.  The 
  198. opcode bytes given there are 80 /5 ib.  The "/5" denotes an 
  199. effective-address byte, whose value will be taken from column 5 
  200. of the table below.  The offset 17 decimal, which is 11 hex, will 
  201. fit in a single "d8" byte, so we take our value from the "[BX] + 
  202. d8" row.  The table tells us that the effective address byte is 
  203. 6F.  Immediately following the 6F is the offset, 11 hex.  
  204. Following that is the ib-value of 100 decimal, which is 64 hex.  
  205. So the bytes generated by SUB B[BX+17],100 are 80 6F 11 64.  
  206.                                                           6-5
  207.  
  208. Table of Effective Address byte values
  209.  
  210. s  =    ES   CS   SS   DS
  211. rb =    AL   CL   DL   BL   AH   CH   DH   BH
  212. rw =    AX   CX   DX   BX   SP   BP   SI   DI
  213. digit=   0    1    2    3    4    5    6    7
  214.                                                Effective
  215. EA byte                                         address:
  216. values: 00   08   10   18   20   28   30   38    [BX + SI]
  217.         01   09   11   19   21   29   31   39    [BX + DI]
  218.         02   0A   12   1A   22   2A   32   3A    [BP + SI]
  219.         03   0B   13   1B   23   2B   33   3B    [BP + DI]
  220.         04   0C   14   1C   24   2C   34   3C    [SI]
  221.         05   0D   15   1D   25   2D   35   3D    [DI]
  222.         06   0E   16   1E   26   2E   36   3E    d16 (simple var)
  223.         07   0F   17   1F   27   2F   37   3F    [BX]
  224.         40   48   50   58   60   68   70   78    [BX + SI] + d8
  225.         41   49   51   59   61   69   71   79    [BX + DI] + d8
  226.         42   4A   52   5A   62   6A   72   7A    [BP + SI] + d8
  227.         43   4B   53   5B   63   6B   73   7B    [BP + DI] + d8
  228.         44   4C   54   5C   64   6C   74   7C    [SI] + d8
  229.         45   4D   55   5D   65   6D   75   7D    [DI] + d8
  230.         46   4E   56   5E   66   6E   76   7E    [BP] + d8
  231.         47   4F   57   5F   67   6F   77   7F    [BX] + d8
  232.         80   88   90   98   A0   A8   B0   B8    [BX + SI] + d16
  233.         81   89   91   99   A1   A9   B1   B9    [BX + DI] + d16
  234.         82   8A   92   9A   A2   AA   B2   BA    [BP + SI] + d16
  235.         83   8B   93   9B   A3   AB   B3   BB    [BP + DI] + d16
  236.         84   8C   94   9C   A4   AC   B4   BC    [SI] + d16
  237.         85   8D   95   9D   A5   AD   B5   BD    [DI] + d16
  238.         86   8E   96   9E   A6   AE   B6   BE    [BP] + d16
  239.         87   8F   97   9F   A7   AF   B7   BF    [BX] + d16
  240.         C0   C8   D0   D8   E0   E8   F0   F8    ew=AX   eb=AL
  241.         C1   C9   D1   D9   E1   E9   F1   F9    ew=CX   eb=CL
  242.         C2   CA   D2   DA   E2   EA   F2   FA    ew=DX   eb=DL
  243.         C3   CB   D3   DB   E3   EB   F3   FB    ew=BX   eb=BL
  244.         C4   CC   D4   DC   E4   EC   F4   FC    ew=SP   eb=AH
  245.         C5   CD   D5   DD   E5   ED   F5   FD    ew=BP   eb=CH
  246.         C6   CE   D6   DE   E6   EE   F6   FE    ew=SI   eb=DH
  247.         C7   CF   D7   DF   E7   EF   F7   FF    ew=DI   eb=BH
  248.  
  249. d8 denotes an 8-bit displacement following the EA byte,
  250. to be sign-extended and added to the index.
  251.  
  252. d16 denotes a 16-bit displacement following the EA byte,
  253. to be added to the index.
  254.  
  255. Default segment register is SS for effective addresses containing
  256. a BP index; DS for other memory effective addresses.
  257.                                                           6-6
  258. How to Read the Instruction Set Chart
  259.  
  260. The chart below summarizes the machine instructions you can 
  261. program with A86.  In order to use the chart, you need to learn 
  262. the meanings of the specifiers (each given by 2 lower-case 
  263. letters), that follow most of the instruction mnemonics.  Each 
  264. specifier indicates the type of operand (register byte, immediate 
  265. word, etc.) that follows the mnemonic to produce the given 
  266. opcodes.  
  267.  
  268. "c" means the operand is a code label, pointing to a part of the 
  269.     program to be jumped to or called.  A86 will also accept a 
  270.     constant offset in this place (or a constant segment-offset 
  271.     pair in the case of "cd").  "cb" is a label within about 128 
  272.     bytes (in either direction) of the current location.  "cw" is 
  273.     a label within the same code segment as this program; "cd" is 
  274.     a pair of constants separated by a colon-- the segment value 
  275.     to the left of the colon, and the offset to the right.  Note 
  276.     that in both the cb and cw cases, the object code generated 
  277.     is the offset from the location following the current 
  278.     instruction, not the absolute location of the label operand.  
  279.     In some assemblers (most notably for the Z-80 processor) you 
  280.     have to code this offset explicitly by putting "$-" before 
  281.     every relative jump operand in your source code.  You do NOT 
  282.     need to, and should not do so with A86.  
  283.  
  284. "e" means the operand is an Effective Address.  The concept of an 
  285.     Effective Address is central to the 86 machine architecture, 
  286.     and thus to 86 assembly language programming.  It is 
  287.     described in detail at the start of Chapter 8.  We summarize 
  288.     here by saying that an Effective Address is either a general-
  289.     purpose register, a memory variable, or an indexed memory 
  290.     quantity.  For example, the instruction "ADD rb,eb" includes 
  291.     the instructions: ADD AL,BL, or ADD CH,BYTEVAR, or ADD 
  292.     DL,B[BX+17].  
  293.  
  294. "i" means the operand is an immediate constant, provided as part 
  295.     of the instruction itself.  "ib" is a byte-sized constant; 
  296.     "iw" is a constant occupying a full 16-bit word.  The operand 
  297.     can also be a label, defined with a colon.  In that case, the 
  298.     immediate constant which is the location of the label is 
  299.     used.  Examples:  "MOV rw,iw" includes the instructions: MOV 
  300.     AX,17, or MOV SI,VAR_ARRAY, where "VAR_ARRAY:" appears 
  301.     somewhere in the program, defined with a colon.  NOTE that if 
  302.     VAR_ARRAY were defined without a colon, e.g., "VAR_ARRAY DW 
  303.     1,2,3", then "MOV SI,VAR_ARRAY" would be a "MOV rw,ew" NOT a 
  304.     "MOV rw,iw".  The MOV would move the contents of memory at 
  305.     VAR_ARRAY (in this case 1) into SI, instead of the location 
  306.     of the memory. To load the location, you can code "MOV 
  307.     SI,OFFSET VAR_ARRAY".  
  308.  
  309. "m" means a memory variable or an indexed memory quantity; i.e., 
  310.     any Effective Address EXCEPT a register.  
  311.  
  312. "r" means the operand is a general-purpose register.  The 8 "rb" 
  313.     registers are AL,BL,CL,DL,AH,BH,CH,DH; the 8 "rw" registers 
  314.     are AX,BX,CX,DX,SI, DI,BP,SP.  
  315.  
  316.  
  317.